Skip to main content

Creating Documents from Scratch

Creating a Basic Document​

Using OpenXML SDK​

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System.IO;

public static void CreateBasicDocument(string filepath)
{
using (WordprocessingDocument doc = WordprocessingDocument.Create(
filepath, WordprocessingDocumentType.Document))
{
// Add main document part
MainDocumentPart mainPart = doc.AddMainDocumentPart();
mainPart.Document = new Document();
Body body = mainPart.Document.AppendChild(new Body());

// Add a paragraph with text
Paragraph para = body.AppendChild(new Paragraph());
Run run = para.AppendChild(new Run());
run.AppendChild(new Text("Hello World!"));

// Save
mainPart.Document.Save();
}
}

AppraiSys Pattern: Default Document​

From DefaultDocument.cs:

public static void CreateDefaultDocument(MemoryStream documentStream)
{
using (var document = WordprocessingDocument.Create(
documentStream,
WordprocessingDocumentType.Document,
true))
{
// 1. Create main document part
var mainPart = document.AddMainDocumentPart();
mainPart.Document = new Document();
var body = mainPart.Document.AppendChild(new Body());

// 2. Create styles part
var styleDefinitionsPart = mainPart.AddNewPart<StyleDefinitionsPart>();
var styles = new Styles();
styleDefinitionsPart.Styles = styles;

// 3. Add document defaults
CreateDocDefaults(styles);

// 4. Add standard styles
CreateParagraphStyle(styles, "Normal", "Normal", 99);
CreateParagraphStyle(styles, "Heading1", "Heading 1", 98, "Normal");
CreateParagraphStyle(styles, "Heading2", "Heading 2", 97, "Normal");
CreateCharacterStyle(styles, "DefaultParagraphFont", "Default Paragraph Font", 0);
CreateTableStyle(styles, "NormalTable", "Normal Table", 99);

// 5. Create numbering part
var numberingDefinitionsPart = mainPart.AddNewPart<NumberingDefinitionsPart>();
numberingDefinitionsPart.Numbering = new Numbering();

mainPart.Document.Save();
}
}

Document Defaults​

private static void CreateDocDefaults(Styles styles)
{
var docDefaults = new DocDefaults();

// Run defaults
var runPropertiesDefault = new RunPropertiesDefault();
var runPropertiesBaseStyle = new RunPropertiesBaseStyle();
runPropertiesBaseStyle.AppendChild(new RunFonts
{
Ascii = "Times New Roman",
HighAnsi = "Times New Roman",
EastAsia = "Times New Roman",
ComplexScript = "Times New Roman"
});
runPropertiesBaseStyle.AppendChild(new FontSize { Val = "22" }); // 11pt
runPropertiesBaseStyle.AppendChild(new FontSizeComplexScript { Val = "22" });
runPropertiesBaseStyle.AppendChild(new Languages
{
Val = "en-US",
EastAsia = "en-US",
Bidi = "ar-SA"
});
runPropertiesDefault.AppendChild(runPropertiesBaseStyle);
docDefaults.AppendChild(runPropertiesDefault);

// Paragraph defaults
var paragraphPropertiesDefault = new ParagraphPropertiesDefault();
var paragraphPropertiesBaseStyle = new ParagraphPropertiesBaseStyle();
paragraphPropertiesBaseStyle.AppendChild(new SpacingBetweenLines
{
After = "0",
Line = "276",
LineRule = LineSpacingRuleValues.Auto
});
paragraphPropertiesDefault.AppendChild(paragraphPropertiesBaseStyle);
docDefaults.AppendChild(paragraphPropertiesDefault);

styles.AppendChild(docDefaults);
}

Creating Paragraph Styles​

private static void CreateParagraphStyle(
Styles styles,
string styleId,
string styleName,
int uiPriority,
string basedOn = null)
{
var style = new Style
{
Type = StyleValues.Paragraph,
StyleId = styleId
};

style.AppendChild(new Name { Val = styleName });
style.AppendChild(new UIPriority { Val = uiPriority });

if (basedOn != null)
{
style.AppendChild(new BasedOn { Val = basedOn });
}

// Style-specific properties
if (styleId == "Heading1")
{
var paragraphProperties = new ParagraphProperties();
paragraphProperties.AppendChild(new KeepNext());
paragraphProperties.AppendChild(new KeepLines());
paragraphProperties.AppendChild(new SpacingBetweenLines
{
Before = "240",
After = "120"
});
paragraphProperties.AppendChild(new OutlineLevel { Val = 0 });
style.AppendChild(paragraphProperties);

var runProperties = new RunProperties();
runProperties.AppendChild(new Bold());
runProperties.AppendChild(new FontSize { Val = "32" }); // 16pt
style.AppendChild(runProperties);
}

styles.AppendChild(style);
}

Creating Table Styles​

AppraiSys NormalTable​

private static void CreateTableStyle(
Styles styles,
string styleId,
string styleName,
int uiPriority)
{
var style = new Style
{
Type = StyleValues.Table,
StyleId = styleId
};

style.AppendChild(new Name { Val = styleName });
style.AppendChild(new UIPriority { Val = uiPriority });

var tableProperties = new TableProperties();

// Table indentation
tableProperties.AppendChild(new TableIndentation
{
Width = 0,
Type = TableWidthUnitValues.Dxa
});

// Cell margins
tableProperties.AppendChild(new TableCellMarginDefault(
new TopMargin { Width = "0", Type = TableWidthUnitValues.Dxa },
new TableCellLeftMargin { Width = 108, Type = TableWidthValues.Dxa },
new BottomMargin { Width = "0", Type = TableWidthUnitValues.Dxa },
new TableCellRightMargin { Width = 108, Type = TableWidthValues.Dxa }
));

style.AppendChild(tableProperties);

// Table row properties
style.AppendChild(new TableRowProperties(
new CantSplit() // Keep rows together
));

styles.AppendChild(style);
}

PropertyImagesTable Style​

private static Style CreatePropertyImagesTableStyle()
{
var style = new Style
{
Type = StyleValues.Table,
StyleId = "PropertyImagesTable"
};

style.AppendChild(new Name { Val = "Property Images Table" });
style.AppendChild(new UIPriority { Val = 50 });

var tableProperties = new TableProperties();

// Center table
tableProperties.AppendChild(new TableJustification
{
Val = TableRowAlignmentValues.Center
});

// Cell spacing (gap between cells)
tableProperties.AppendChild(new TableCellSpacing
{
Width = "100",
Type = TableWidthUnitValues.Dxa
});

// No borders
tableProperties.AppendChild(new TableBorders(
new TopBorder { Val = BorderValues.None },
new BottomBorder { Val = BorderValues.None },
new LeftBorder { Val = BorderValues.None },
new RightBorder { Val = BorderValues.None },
new InsideHorizontalBorder { Val = BorderValues.None },
new InsideVerticalBorder { Val = BorderValues.None }
));

// Zero cell margins
tableProperties.AppendChild(new TableCellMarginDefault(
new TopMargin { Width = "0", Type = TableWidthUnitValues.Dxa },
new TableCellLeftMargin { Width = 0, Type = TableWidthValues.Dxa },
new BottomMargin { Width = "0", Type = TableWidthUnitValues.Dxa },
new TableCellRightMargin { Width = 0, Type = TableWidthValues.Dxa }
));

style.AppendChild(tableProperties);

// Cell properties
var tableCellProperties = new TableCellProperties();
tableCellProperties.AppendChild(new VerticalMerge
{
Val = MergedCellValues.Continue
});
tableCellProperties.AppendChild(new TableCellVerticalAlignment
{
Val = TableVerticalAlignmentValues.Top
});

style.AppendChild(tableCellProperties);

return style;
}

Creating Character Styles​

private static void CreateCharacterStyle(
Styles styles,
string styleId,
string styleName,
int uiPriority)
{
var style = new Style
{
Type = StyleValues.Character,
StyleId = styleId,
Default = true
};

style.AppendChild(new Name { Val = styleName });
style.AppendChild(new UIPriority { Val = uiPriority });

styles.AppendChild(style);
}

Creating Numbering Styles​

AppraiSys Bullet List​

private static void CreateNumberingStyle(
Styles styles,
string styleId,
string styleName,
int abstractNumId)
{
var style = new Style
{
Type = StyleValues.Numbering,
StyleId = styleId
};

style.AppendChild(new Name { Val = styleName });
style.AppendChild(new UIPriority { Val = 99 });
style.AppendChild(new BasedOn { Val = "Normal" });

var paragraphProperties = new ParagraphProperties();
paragraphProperties.AppendChild(new NumberingProperties(
new NumberingId { Val = abstractNumId }
));
style.AppendChild(paragraphProperties);

styles.AppendChild(style);
}

Numbering Definition​

public static void CreateBulletList(NumberingDefinitionsPart numberingPart)
{
// Abstract numbering definition
var abstractNum = new AbstractNum { AbstractNumberId = 0 };

abstractNum.AppendChild(new MultiLevelType { Val = MultiLevelValues.HybridMultilevel });

// Level 0 (bullet)
var level0 = new Level { LevelIndex = 0 };
level0.AppendChild(new StartNumberingValue { Val = 1 });
level0.AppendChild(new NumberingFormat { Val = NumberFormatValues.Bullet });
level0.AppendChild(new LevelText { Val = "●" });
level0.AppendChild(new LevelJustification { Val = LevelJustificationValues.Left });

var previousParagraphProperties = new PreviousParagraphProperties();
previousParagraphProperties.AppendChild(new Indentation
{
Left = "720",
Hanging = "360"
});
level0.AppendChild(previousParagraphProperties);

var numberingSymbolRunProperties = new NumberingSymbolRunProperties();
numberingSymbolRunProperties.AppendChild(new RunFonts
{
Ascii = "Symbol",
HighAnsi = "Symbol",
Hint = FontTypeHintValues.Default
});
level0.AppendChild(numberingSymbolRunProperties);

abstractNum.AppendChild(level0);

numberingPart.Numbering.AppendChild(abstractNum);

// Numbering instance
var numberingInstance = new NumberingInstance { NumberID = 1 };
numberingInstance.AppendChild(new AbstractNumId { Val = 0 });
numberingPart.Numbering.AppendChild(numberingInstance);
}

Adding Content​

Add Simple Paragraph​

public static Paragraph CreateParagraph(string text, string style = null)
{
var paragraph = new Paragraph();

if (style != null)
{
var paragraphProperties = new ParagraphProperties();
paragraphProperties.AppendChild(new ParagraphStyleId { Val = style });
paragraph.AppendChild(paragraphProperties);
}

var run = new Run();
run.AppendChild(new Text(text));
paragraph.AppendChild(run);

return paragraph;
}

Add Formatted Text​

public static Paragraph CreateFormattedParagraph(
string text,
bool bold = false,
bool italic = false,
string color = null,
int? fontSize = null,
JustificationValues alignment = JustificationValues.Left)
{
var paragraph = new Paragraph();

// Paragraph properties
var paragraphProperties = new ParagraphProperties();
paragraphProperties.AppendChild(new Justification { Val = alignment });
paragraph.AppendChild(paragraphProperties);

// Run
var run = new Run();

// Run properties
var runProperties = new RunProperties();

if (bold)
runProperties.AppendChild(new Bold());

if (italic)
runProperties.AppendChild(new Italic());

if (color != null)
runProperties.AppendChild(new Color { Val = color });

if (fontSize.HasValue)
runProperties.AppendChild(new FontSize { Val = (fontSize.Value * 2).ToString() });

run.AppendChild(runProperties);
run.AppendChild(new Text(text));
paragraph.AppendChild(run);

return paragraph;
}

Complete Example: AppraiSys Report Template​

public static MemoryStream CreateReportTemplate()
{
var stream = new MemoryStream();

using (var document = WordprocessingDocument.Create(
stream, WordprocessingDocumentType.Document, true))
{
var mainPart = document.AddMainDocumentPart();
mainPart.Document = new Document();
var body = mainPart.Document.AppendChild(new Body());

// Add styles
var stylesPart = mainPart.AddNewPart<StyleDefinitionsPart>();
var styles = new Styles();
CreateDocDefaults(styles);
CreateParagraphStyle(styles, "Normal", "Normal", 99);
CreateParagraphStyle(styles, "Heading1", "Heading 1", 98, "Normal");
CreateParagraphStyle(styles, "Heading2", "Heading 2", 97, "Normal");
CreateTableStyle(styles, "NormalTable", "Normal Table", 99);
stylesPart.Styles = styles;

// Add content
body.AppendChild(CreateParagraph("Appraisal Report", "Heading1"));
body.AppendChild(CreateParagraph("")); // Empty paragraph

// Property information section
body.AppendChild(CreateParagraph("Property Information", "Heading2"));

// Add content control for address
var sdt = CreateContentControl("PropertyAddress", "Property Address");
body.AppendChild(sdt);

// Add table
var table = CreatePropertyInfoTable();
body.AppendChild(table);

mainPart.Document.Save();
}

stream.Position = 0;
return stream;
}

Helper: Create Content Control​

public static SdtBlock CreateContentControl(string tag, string alias)
{
var sdtBlock = new SdtBlock();

// Properties
var sdtProperties = new SdtProperties();
sdtProperties.AppendChild(new Tag { Val = tag });
sdtProperties.AppendChild(new Alias { Val = alias });
sdtProperties.AppendChild(new SdtId { Val = GenerateUniqueId() });
sdtBlock.AppendChild(sdtProperties);

// Content
var sdtContent = new SdtContentBlock();
var paragraph = new Paragraph();
var run = new Run();
run.AppendChild(new Text("[" + alias + "]"));
paragraph.AppendChild(run);
sdtContent.AppendChild(paragraph);
sdtBlock.AppendChild(sdtContent);

return sdtBlock;
}

private static int GenerateUniqueId()
{
return new Random().Next(100000, 999999);
}

Next Steps​

➡️ Next: Table Creation

Related:


💡 Remember: Always create styles part before adding styled content. Default document setup is critical for consistency!